﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using ImageProcessor.Imaging;
using Point = System.Drawing.Point;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Trace.WriteLine("aaaaaaaaaaaaaaaaaaaa");
        }

        private void button1_Click(object sender, EventArgs e)
        {


            //            Image<Bgr,byte> sub=new Image<Bgr, byte>("C:\\Users\\ACER\\Desktop\\repos\\sim\\3.bmp");
            //            Image<Bgr, byte> par = new Image<Bgr, byte>("C:\\Users\\ACER\\Desktop\\c.png");
            //            Image<Gray, float> c = par.MatchTemplate(sub, TemplateMatchingType.Ccoeff);
            //            CvInvoke.Normalize(c,c);
            //            List<Point> ps=new List<Point>();
            //            for (int i = 0; i < c.Size.Width; i++)
            //            {
            //                for (int j = 0; j < c.Size.Height; j++)
            //                {
            //                    var cc=c[j,i];
            //                    if (cc.Intensity>0.1)
            //                    {
            //                        Console.WriteLine(cc.Intensity);
            //                        ps.Add(new Point(i,j));
            //                    }
            //                }
            //            }
            //            foreach (var p in ps)
            //            {
            //                par.Draw(new Rectangle(p.X,p.Y,sub.Width,sub.Height),new Bgr(Color.White),-1 );
            //            }
            System.Threading.Tasks.Parallel.ForEach(Directory.GetFiles("C:\\Users\\ACER\\Desktop\\522"), (s =>
             {
                 ReplaceColor(s, Color.FromArgb(255, 166, 166), Color.White, 84);
                 ReplaceColor(s, Color.FromArgb(0xdd, 0xdd, 0xdd), Color.White, 84);
                 ReplaceColor(s, Color.FromArgb(0, 0, 255), Color.Black, 84);
                 ReplaceColor(s, Color.FromArgb(0x40, 0x70, 0x3e), Color.Black, 0x80);
                 FindPicReplaceIt(s, "C:\\Users\\ACER\\Desktop\\repos\\sim\\3.bmp", 0.05f, TemplateMatchingType.Ccorr);
                 FindPicReplaceIt(s, "C:\\Users\\ACER\\Desktop\\repos\\sim\\1.bmp", 0.05f, TemplateMatchingType.Ccorr,new Size(150,16));
                 Trace.WriteLine(s + "//");
             }));

            System.Threading.Tasks.Parallel.ForEach(Directory.GetFiles("C:\\Users\\ACER\\Desktop\\523"), (s =>
            {
                ReplaceColor(s, Color.FromArgb(255, 166, 166), Color.White, 84);
                ReplaceColor(s, Color.FromArgb(0xdd, 0xdd, 0xdd), Color.White, 0x20);
                ReplaceColor(s, Color.FromArgb(0, 0, 255), Color.Black, 84);
                ReplaceColor(s, Color.FromArgb(0x40, 0x70, 0x3e), Color.Black, 0x80);
                FindPicReplaceIt(s, "C:\\Users\\ACER\\Desktop\\repos\\sim\\3.bmp", 0.05f, TemplateMatchingType.Ccorr);
                FindPicReplaceIt(s, "C:\\Users\\ACER\\Desktop\\repos\\sim\\1.bmp", 0.05f, TemplateMatchingType.Ccorr, new Size(150, 16));
                Trace.WriteLine(s + "//");
            }));
            System.Threading.Tasks.Parallel.ForEach(Directory.GetFiles("C:\\Users\\ACER\\Desktop\\524"), (s =>
            {
                ReplaceColor(s, Color.FromArgb(255, 166, 166), Color.White, 84);
                ReplaceColor(s, Color.FromArgb(0xdd, 0xdd, 0xdd), Color.White, 0x20);
                ReplaceColor(s, Color.FromArgb(0, 0, 255), Color.Black, 84);
                ReplaceColor(s, Color.FromArgb(0x40, 0x70, 0x3e), Color.Black, 0x80);
                FindPicReplaceIt(s, "C:\\Users\\ACER\\Desktop\\repos\\sim\\3.bmp", 0.05f, TemplateMatchingType.Ccorr);
                FindPicReplaceIt(s, "C:\\Users\\ACER\\Desktop\\repos\\sim\\1.bmp", 0.05f, TemplateMatchingType.Ccorr, new Size(150, 16));
                Trace.WriteLine(s+"//");
            }));

            MessageBox.Show("ok");

        }

        public void ReplaceColor(string file,Color oldColor,Color newColor,int rc,string newfile=null)
        {
            Image<Bgr, byte> par = new Image<Bgr, byte>(file);
            Bgr newBgr = new Bgr(newColor.B, newColor.G, newColor.R);
            for (int i = 0; i < par.Width; i++)
            {
                for (int j = 0; j < par.Height; j++)
                {
                    Bgr bgr = par[j, i];
                    if (Math.Abs(bgr.Red - oldColor.R) < rc && Math.Abs(bgr.Green - oldColor.G) < rc &&
                        Math.Abs(bgr.Blue - oldColor.B) < rc)
                    {
                        par.Draw(new[] { new Point(i, j), new Point(i, j) }, newBgr, -1);
                    }
                }
            }
            par.Save(newfile ?? file);
        }

        public void FindPicReplaceIt(string parfile, string subfile, float intensity, TemplateMatchingType tmp,
            Size rec = new Size(), string newfile = null)
        {
            Image<Bgr, byte> sub = new Image<Bgr, byte>(subfile);
            Image<Bgr, byte> par = new Image<Bgr, byte>(parfile);
            Image<Gray, float> c = par.MatchTemplate(sub, TemplateMatchingType.Ccoeff);
            CvInvoke.Normalize(c, c);
            List<Point> ps = new List<Point>();
            for (int i = 0; i < c.Size.Width; i++)
            {
                for (int j = 0; j < c.Size.Height; j++)
                {
                    var cc = c[j, i];
                    if (cc.Intensity > intensity)
                    {
                        Console.WriteLine(parfile+" ** "+cc.Intensity + " x:" + i + " y:" + j);
                        ps.Add(new Point(i, j));
                    }
                }
            }
            if (rec.Width == 0 && rec.Height == 0)
            {
                foreach (var p in ps)
                {
                    par.Draw(new Rectangle(p.X, p.Y, sub.Width, sub.Height), new Bgr(Color.White), -1);
                }
            }
            else
            {
                foreach (var p in ps)
                {
                    par.Draw(new Rectangle(p.X, p.Y, rec.Width, rec.Height), new Bgr(Color.White), -1);
                }

            }
//            CvInvoke.EdgePreservingFilter(par,par);
            par.Save(newfile ?? parfile);
        }

        #region 找图

        /// <summary>
        /// 查找图片，不能镂空
        /// </summary>
        /// <param name="subPic"></param>
        /// <param name="parPic"></param>
        /// <param name="searchRect">如果为empty，则默认查找整个图像</param>
        /// <param name="errorRange">容错，单个色值范围内视为正确0~255</param>
        /// <param name="matchRate">图片匹配度，默认90%</param>
        /// <param name="isFindAll">是否查找所有相似的图片</param>
        /// <returns>返回查找到的图片的中心点坐标</returns>
        static List<Point> FindPicture(string subPic, string parPic, Rectangle searchRect, byte errorRange, double matchRate = 0.9, bool isFindAll = false)
        {
            List<Point> ListPoint = new List<Point>();
            var subBitmap = new Bitmap(subPic);
            var parBitmap = new Bitmap(parPic);
            FastBitmap fastsubBitmap = new FastBitmap(subBitmap);
            FastBitmap fastparBitmap = new FastBitmap(parBitmap);
            
            int subWidth = fastsubBitmap.Width;
            int subHeight = fastsubBitmap.Height;
            int parWidth = fastparBitmap.Width;
            int parHeight = fastparBitmap.Height;
            if (searchRect.IsEmpty)
            {
                searchRect = new Rectangle(0, 0, fastparBitmap.Width, fastparBitmap.Height);
            }

            var searchLeftTop = searchRect.Location;
            var searchSize = searchRect.Size;
            Color startPixelColor = fastsubBitmap.GetPixel(0, 0);

            var iMax = searchLeftTop.Y + searchSize.Height - subHeight;//行
            var jMax = searchLeftTop.X + searchSize.Width - subWidth;//列

            int smallOffsetX = 0, smallOffsetY = 0;
            int smallStartX = 0, smallStartY = 0;
            int pointX = -1; int pointY = -1;
            for (int i = searchLeftTop.Y; i < iMax; i++)
            {
                for (int j = searchLeftTop.X; j < jMax; j++)
                {
                    //大图x，y坐标处的颜色值
                    int x = j, y = i;
                    var colorBig = fastparBitmap.GetPixel(x, y);
                   ;
                    if (ColorAEqualColorB(colorBig, startPixelColor, errorRange))
                    {
                        smallStartX = x - smallOffsetX;//待找的图X坐标
                        smallStartY = y - smallOffsetY;//待找的图Y坐标
                        int sum = 0;//所有需要比对的有效点
                        int matchNum = 0;//成功匹配的点
                        for (int m = 0; m < subHeight; m++)
                        {
                            for (int n = 0; n < subWidth; n++)
                            {
                                int x1 = n, y1 = m;
                                var color = fastsubBitmap.GetPixel(x1, y1);

                                sum++;
                                int x2 = smallStartX + x1, y2 = smallStartY + y1;
                                var colorPixel = fastparBitmap.GetPixel(x2, y2);
                                if (ColorAEqualColorB(colorPixel, color, errorRange))
                                {
                                    matchNum++;
                                }
                            }
                        }
                        if ((double)matchNum / sum >= matchRate)
                        {
                            Console.WriteLine((double)matchNum / sum);
                            pointX = smallStartX + (int)(subWidth / 2.0);
                            pointY = smallStartY + (int)(subHeight / 2.0);
                            var point = new Point(pointX, pointY);
                            if (!ListContainsPoint(ListPoint, point, 10))
                            {
                                ListPoint.Add(point);
                            }
                            if (!isFindAll)
                            {
                                goto FIND_END;
                            }
                        }
                    }
                    //小图x1,y1坐标处的颜色值
                }
            }
        FIND_END:
            fastsubBitmap.Dispose();
            fastparBitmap.Dispose();
            subBitmap.Dispose();
            parBitmap.Dispose();
            GC.Collect();
            return ListPoint;
        }
        #endregion
        static bool ListContainsPoint(List<System.Drawing.Point> listPoint, System.Drawing.Point point, double errorRange = 10)
        {
            bool isExist = false;
            foreach (var item in listPoint)
            {
                if (item.X <= point.X + errorRange && item.X >= point.X - errorRange && item.Y <= point.Y + errorRange && item.Y >= point.Y - errorRange)
                {
                    isExist = true;
                }
            }
            return isExist;
        }
        static bool ColorAEqualColorB(System.Drawing.Color colorA, System.Drawing.Color colorB, byte errorRange = 10)
        {
            return colorA.A <= colorB.A + errorRange && colorA.A >= colorB.A - errorRange &&
                   colorA.R <= colorB.R + errorRange && colorA.R >= colorB.R - errorRange &&
                   colorA.G <= colorB.G + errorRange && colorA.G >= colorB.G - errorRange &&
                   colorA.B <= colorB.B + errorRange && colorA.B >= colorB.B - errorRange;

        }

    }
}
